Unit testing an analyzer
To help analyzer authors testing their analyzers, there's a dedicated testing package. It contains easy to use utility functions to create a context for the analyzer and assertion helpers.
FSharp.Analyzers.SDK.Testing.mkOptionsFromProject
creates the FSharpProjectOptions
for the given framework (e.g. net7.0
) and the given list of packages to reference.
FSharp.Analyzers.SDK.Testing.getContext
then takes the FSharpProjectOptions
and the source code to test and creates a CliContext
you can pass along to your analyzer function.
The module FSharp.Analyzers.SDK.Testing.Assert
offers various functions to help with assertion statements from your favorite unit testing framework.
For a complete example of an unit testing project, take a look at OptionAnalyzer.Test
in the samples
folder of the SDK repository.
open FSharp.Compiler.CodeAnalysis
open FSharp.Analyzers.SDK.Testing
open OptionAnalyzer
open NUnit.Framework
let mutable projectOptions: FSharpProjectOptions = FSharpProjectOptions.zero
[<SetUp>]
let Setup () =
task {
let! opts =
mkOptionsFromProject
"net7.0"
[
// The SDK uses this in a "dotnet add package x --version y" command
// to generate the needed FSharpProjectOptions
{ Name = "Newtonsoft.Json"
Version = "13.0.3" } ]
projectOptions <- opts
}
[<Test>]
let ``warnings are emitted`` () =
async {
let source =
"""
module M
let notUsed() =
let option : Option<int> = None
option.Value
"""
let ctx = getContext projectOptions source
let! msgs = optionValueAnalyzer ctx
Assert.IsNotEmpty msgs
Assert.IsTrue(Assert.messageContains "Option.Value" msgs[0])
}
namespace FSharp
--------------------
namespace Microsoft.FSharp
type SetUpAttribute = inherit NUnitAttribute new: unit -> unit
--------------------
SetUpAttribute() : SetUpAttribute
<summary>Creates a classlib project in a temporary folder to gather the needed FSharpProjectOptions.</summary>
<param name="framework">The target framework for the tested code to use. E.g. net6.0, net7.0</param>
<param name="additionalPkgs">A list of additional packages that should be referenced. The tested code can use these.</param>
<returns>FSharpProjectOptions</returns>
type TestAttribute = inherit NUnitAttribute interface ISimpleTestBuilder interface IApplyToTest interface IImplyFixture new: unit -> unit member ApplyToTest: test: Test -> unit member BuildFrom: method: IMethodInfo * suite: Test -> TestMethod member Author: string member Description: string member ExpectedResult: obj ...
--------------------
TestAttribute() : TestAttribute
Assert.IsNotEmpty(aString: string) : unit
Assert.IsNotEmpty(collection: System.Collections.IEnumerable, message: string, [<System.ParamArray>] args: obj array) : unit
Assert.IsNotEmpty(aString: string, message: string, [<System.ParamArray>] args: obj array) : unit
Assert.IsTrue(condition: System.Nullable<bool>) : unit
Assert.IsTrue(condition: bool, message: string, [<System.ParamArray>] args: obj array) : unit
Assert.IsTrue(condition: System.Nullable<bool>, message: string, [<System.ParamArray>] args: obj array) : unit